#!/usr/bin/python
# -*- coding: UTF-8 -*-

# 面向对象编程：类、对象、方法、属性
# 面向过程编程：函数、参数、返回值

# 类：模板、蓝图
# 对象：类的实例化结果
# 方法：类中定义的函数，用于操作对象的数据
# 属性：类中定义的变量，用于描述对象的数据


# 类定义
class Person:
    # 类属性
    species = "Homosapiens"

    # 实例方法
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def say_hello(self):
        print("Hello, my name is " + self.name + "!")

    def get_species(self):
        return self.species


# 实例化对象
person1 = Person("Alice", 25)
person2 = Person("Bob", 30)


# 调用方法
person1.say_hello()
person2.say_hello()

# 访问属性
print(person1.name)
print(person2.age)

# 访问类属性
print(Person.species)

# 调用类方法
print(person1.get_species())
print(person2.get_species())


# 类继承
class Student(Person):
    def __init__(self, name, age, grade):
        super().__init__(name, age)
        self.grade = grade

    def say_hello(self):
        print("Hello, my name is " + self.name + " and I am in grade " + str(self.grade) + "!")


# 实例化子类对象
student1 = Student("Charlie", 20, 3)
student2 = Student("David", 22, 4)


# 调用子类方法
student1.say_hello()
student2.say_hello()


# 访问子类属性
print(student1.grade)
print(student2.age)
# student1.get_species()  # 父类方法不能被子类调用


# 多态
# 父类引用子类对象，调用子类方法
person1 = Student("Alice", 25, 1)
person1.say_hello()  # 调用子类方法

# 子类引用父类对象，调用父类方法
person2 = Person("Bob", 30)
person2.say_hello()  # 调用父类方法

# 子类对象赋值给父类变量，调用父类方法
person3 = Student("Charlie", 20, 3)
person4 = person3
person4.say_hello()  # 调用父类方法

# 子类对象赋值给父类变量，调用子类方法
person5 = Person("David", 22)
person5 = student2
person5.say_hello()  # 调用子类方法

# 子类对象赋值给父类变量，调用父类方法
person6 = Person("Eve", 23)
person6 = student1
person6.say_hello()  # 调用父类方法


